package com.gitee.wsl.compose.chart.xy.bar.bullet.indicator

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi

const val DefaultSizeFraction = 0.75f

/**
 * A line for comparative measure indicators.
 * @param heightFraction The fraction of the overall bullet graph bar area height for the extent of the line
 * @param width The thickness of the line, defaults to 2.dp
 */
@ExperimentalKoalaPlotApi
@Composable
 fun LineIndicator(
    color: Color = MaterialTheme.colorScheme.primary,
    heightFraction: Float = DefaultSizeFraction,
    width: Dp = 2.dp
) {
    val shape = LineShape(heightFraction, width)
    Box(
        modifier = Modifier.fillMaxSize().drawBehind {
            val outline = shape.createOutline(this.size, layoutDirection, this)
            drawOutline(outline, SolidColor(color), style = Fill)
        }.clip(shape)
    )
}


/**
 * A line shape for comparative measure indicators.
 * @param heightFraction The fraction of the overall shape height for the extent of the line
 * @param width The fraction of the overall shape width for the thickness of the line
 */
class LineShape(
    val heightFraction: Float,
    val width: Dp
) : Shape {
    override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density) =
        Outline.Generic(
            Path().apply {
                val widthPx = with(density) {
                    if (width == Dp.Hairline) {
                        1
                    } else {
                        width.roundToPx()
                    }
                }
                val vMargin = (size.height - size.height * heightFraction) / 2f
                val hMargin = (size.width - widthPx) / 2f

                moveTo(hMargin, vMargin)
                lineTo(size.width - hMargin, vMargin)
                lineTo(size.width - hMargin, size.height - vMargin)
                lineTo(hMargin, size.height - vMargin)
                lineTo(hMargin, vMargin)
            }
        )

    override fun toString(): String = "LineShape"
}